package com.vip.jwt.common.utils.app;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.vip.jwt.common.utils.sign.ZFBSignUtil;
import com.vip.jwt.common.utils.xcx.Constants;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ResourceUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付工具类
 */
public class APPZFBPayUtil {

    @Getter
    private static String APP_ID;

    @Getter
    private static String PRIVATE_KEY;

    @Getter
    private static String PUBLIC_KEY;

    @Getter
    private static String NOTIFY_URL;

    @Value("${app-zfb-appid}")
    public void setAppId(String appId) {
        APP_ID = appId;
    }

    @Value("${zfb-pay-private-key}")
    public void setPrivateKey(String privateKey){
        PRIVATE_KEY = privateKey;
    }

    @Value("${zfb-pay-public-key}")
    public void setPublicKey(String publicKey){
        PUBLIC_KEY = publicKey;
    }

    @Value("${zfb-pay-notifyurl}")
    public void setNotifyUrl(String notifyUrl){
        NOTIFY_URL = notifyUrl;
    }

    /**
     * 构造Client
     * @return
     */
    private static DefaultAlipayClient getCertAlipayRequest() throws AlipayApiException, FileNotFoundException {
        String serverUrl = "https://openapi.alipay.com/gateway.do";
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl(serverUrl);
        certAlipayRequest.setAppId(APP_ID);
        certAlipayRequest.setPrivateKey(PRIVATE_KEY);
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("utf-8");
        certAlipayRequest.setSignType(Constants.RSA2);
        //注意：如果打jar包这里是获取不到路径的
        //解决方法：将证书放在本地，使用本地路径，例如："C:\\Users\\Administrator\\Desktop\\"
        String rootPath = ResourceUtils.getURL("classpath:").getPath();
        certAlipayRequest.setCertPath(rootPath+"crt/appCertPublicKey_2021001195623396.crt");
        certAlipayRequest.setAlipayPublicCertPath(rootPath+"crt/alipayCertPublicKey_RSA2.crt");
        certAlipayRequest.setRootCertPath(rootPath+"crt/alipayRootCert.crt");
        DefaultAlipayClient defaultAlipayClient = new DefaultAlipayClient(certAlipayRequest);
        defaultAlipayClient.setAlipayPublicKey(PUBLIC_KEY);
        return defaultAlipayClient;
    }

    /**
     * 授权
     * 支付宝账户的唯一标识：userId
     * @return
     */
    public static String getUserInfo(String code) throws AlipayApiException, FileNotFoundException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipaySystemOauthTokenRequest tokenRequest = new AlipaySystemOauthTokenRequest();
        tokenRequest.setGrantType("authorization_code");
        tokenRequest.setCode(code);
        AlipaySystemOauthTokenResponse response = defaultAlipayClient.certificateExecute(tokenRequest);
        return response.getBody();
    }

    /**
     * 统一下单
     * @param subject 商品描述
     * @param outTradeNo 商户订单号
     * @param totalAmount 金额
     * @return
     */
    public static String unifiedOrder(String subject,String outTradeNo,String totalAmount) throws AlipayApiException, FileNotFoundException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipayTradeAppPayRequest tradeAppPayRequest = new AlipayTradeAppPayRequest();
        tradeAppPayRequest.setNotifyUrl(NOTIFY_URL);
        Map<String,String> params = new HashMap<>(16);
        params.put("out_trade_no", outTradeNo);
        params.put("total_amount",totalAmount);
        params.put("subject",subject);
        String dataJson = JSONUtil.toJsonStr(params);
        tradeAppPayRequest.setBizContent(dataJson);
        AlipayTradeAppPayResponse response = defaultAlipayClient.certificateExecute(tradeAppPayRequest);
        return response.getBody();
    }

    /**
     * 关闭订单
     * @param tradeNo 交易流水号
     * @param outTradeNo 商户订单号
     * @return
     * @throws FileNotFoundException
     * @throws AlipayApiException
     */
    public static String closeOrder(String tradeNo,String outTradeNo) throws FileNotFoundException, AlipayApiException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipayTradeCloseRequest tradeCloseRequest = new AlipayTradeCloseRequest();
        Map<String,String> params = new HashMap<>(16);
        params.put("trade_no",tradeNo);
        params.put("out_trade_no", outTradeNo);
        String dataJson = JSONUtil.toJsonStr(params);
        tradeCloseRequest.setBizContent(dataJson);
        AlipayTradeCloseResponse response = defaultAlipayClient.certificateExecute(tradeCloseRequest);
        return response.getBody();
    }

    /**
     * 查询订单
     * @param outTradeNo 商户订单号
     * @param tradeNo 支付宝交易号
     *                注意：两个号不能同时传空
     * @return
     */
    public static String queryOrder(String outTradeNo,String tradeNo) throws FileNotFoundException, AlipayApiException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipayTradeQueryRequest tradeQueryRequest = new AlipayTradeQueryRequest();
        Map<String,String> params = new HashMap<>(16);
        params.put("trade_no",tradeNo);
        params.put("out_trade_no", outTradeNo);
        String dataJson = JSONUtil.toJsonStr(params);
        tradeQueryRequest.setBizContent(dataJson);
        AlipayTradeQueryResponse response = defaultAlipayClient.certificateExecute(tradeQueryRequest);
        return response.getBody();
    }

    /**
     * 退款
     * @param outTradeNo 商户订单号
     * @param tradeNo 支付宝交易号
     * @param refundAmount 退款金额
     *                     注意：商户订单号和支付宝交易号不能同时为空
     * @return
     * @throws FileNotFoundException
     * @throws AlipayApiException
     */
    public static String refund(String outTradeNo,String tradeNo,String refundAmount) throws FileNotFoundException, AlipayApiException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipayTradeRefundRequest tradeRefundRequest = new AlipayTradeRefundRequest();
        tradeRefundRequest.setNotifyUrl(NOTIFY_URL);
        Map<String,String> params = new HashMap<>(16);
        params.put("out_trade_no",outTradeNo);
        params.put("trade_no",tradeNo);
        params.put("refund_amount",refundAmount);
        String dataJson = JSONUtil.toJsonStr(params);
        tradeRefundRequest.setBizContent(dataJson);
        AlipayTradeRefundResponse response = defaultAlipayClient.certificateExecute(tradeRefundRequest);
        return response.getBody();
    }

    /**
     * 提现/转账
     * @param orderTitle 转账标题
     * @param outTradeNo 商户订单号
     * @param transAmount 订单总金额
     * @param identity 用户支付宝UID（获取途径：开放平台->账户中心->账号ID）或者手机号
     *                 identity_type为ALIPAY_LOGON_ID时，identity传入UID
     *                 identity_type为ALIPAY_USER_ID时，identity传入手机号
     * @param name 用户真实姓名
     * @return
     * @throws FileNotFoundException
     * @throws AlipayApiException
     */
    public static String transferAccounts(String orderTitle,String outTradeNo,String transAmount,String identity,String name) throws FileNotFoundException, AlipayApiException {
        DefaultAlipayClient defaultAlipayClient = getCertAlipayRequest();
        AlipayFundTransUniTransferRequest fundTransUniTransferRequest =new AlipayFundTransUniTransferRequest();
        fundTransUniTransferRequest.setNotifyUrl(NOTIFY_URL);
        Map<String,String> params = new HashMap<>(16);
        params.put("out_biz_no",outTradeNo);
        params.put("trans_amount",transAmount);
        params.put("product_code","TRANS_ACCOUNT_NO_PWD");
        params.put("biz_scene","DIRECT_TRANSFER");
        params.put("order_title",orderTitle);
        JSONObject payeeInfoObj = new JSONObject();
        payeeInfoObj.put("identity",identity);
        payeeInfoObj.put("identity_type","ALIPAY_LOGON_ID");
        payeeInfoObj.put("name",name);
        params.put("payee_info", JSONUtil.toJsonStr(payeeInfoObj));
        String dataJson = JSONUtil.toJsonStr(params);
        fundTransUniTransferRequest.setBizContent(dataJson);
        AlipayFundTransUniTransferResponse response = defaultAlipayClient.certificateExecute(fundTransUniTransferRequest);
        return response.getBody();
    }

}
